-
-
Notifications
You must be signed in to change notification settings - Fork 893
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
Add types for custom tags on component prop #622
Comments
The types expect valid HTML, with TS 4.4 I could see custom elements like export interface CustomElements {
[name: `${string}-${string}`]: NormalComponent
} I'm not sure I see |
Another approach, which I believe works today, would be to extend the declare global {
namespace JSX {
// this merges with the existing intrinsic elements, adding 'my-custom-tag' and its props
interface IntrinsicElements {
'my-custom-tag': {'my-custom-attribute': string}
}
}
} thoughts @wooorm on preferred approach? |
this also relates to #623 (review) |
OH yeah sorry for the late reply :-) We wanted to add something like https://github.com/elviswolcott/remark-admonitions to our markdown but have more controll over the generated html. So we use https://github.com/remarkjs/remark-directive and add a simple 'plugin'. The markdown looks e.g. like this: :::note
Ab est nihil vero non sequi sapiente. Omnis doloremque temporibus
::: This is the 'plugin' function customNotesPlugin() {
return function transformer(tree: Node) {
const visitor: Visitor<
Node & { attributes: Record<string, string>; name: string }
> = (node) => {
if (node.name !== 'note') return
const data = node.data || (node.data = {})
data.hName = 'note'
data.hProperties = { title: node.attributes.title ?? 'Note' }
}
visit(tree, ['containerDirective'], visitor)
}
} And then this the ReactMakrdown instance: <ReactMarkdown
remarkPlugins={[
remarkDirective,
customNotesPlugin,
]}
components={{
note: ({ title, children }) => {
return (
<Note title={title as string}>{children}</Note>
)
},
}}
{...props}
/> For me simply extending I could do what Also the docs say:
|
Thanks for sharing!
A PR improving documentation would be welcome!
Up to you on the preferred way to render HTML, custom elements are also supported
HTML supports custom elements (https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements), but they come with specific naming restrictions
|
Closing this as I feel this is something related more to how to deal with TypeScript, React, and JSX, rather than something about markdown and react-markdown. I’d say a link to the https://www.typescriptlang.org/docs/handbook/jsx.html#intrinsic-elements could be added somewhere, but I’m also fine with leaving this specialised knowledge out of the readme |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
While understanding how to work with with custom tags and components I got an idea, a possible alternative resolution for these issues. (Is this the right place to put this?) Currently the type of the Could we instead have a type parameter (generics) for ReactMarkdown defaulting to IntrinsicElements that could be overridden locally if needed -- without modifying any global types. |
For the use case described in this PR it is not misuse.
Maybe?
|
@ChristianMurphy While I agree that extending I added this to my global type definition: declare global {
namespace JSX {
interface IntrinsicElements {
"full-bleed": { "src" : string };
}
}
} but trying to register a component for my custom tag fails with this error:
The type definition in lib/ast-to-react.js seems to be correctly pointing towards the global type NormalComponents = {
a: "a" | ((props: React.ClassAttributes<HTMLAnchorElement> & React.AnchorHTMLAttributes<HTMLAnchorElement> & ReactMarkdownProps) => ReactNode);
abbr: "abbr" | ((props: React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement> & ReactMarkdownProps) => ReactNode);
address: "address" | ((props: React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement> & ReactMarkdownProps) => ReactNode);
area: "area" | ((props: React.ClassAttributes<HTMLAreaElement> & React.AreaHTMLAttributes<HTMLAreaElement> & ReactMarkdownProps) => ReactNode);
article: "article" | ((props: React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement> & ReactMarkdownProps) => ReactNode);
aside: "aside" | ((props: React.ClassAttributes<HTMLElement> & React.HTMLAttributes<HTMLElement> & ReactMarkdownProps) => ReactNode);
... 168 more ...;
view: "view" | ((props: React.SVGProps<SVGViewElement> & ReactMarkdownProps) => ReactNode);
} this seemingly results in me being unable to extend the type definitions for the |
🤔 hmm this seems to be an annoying quirk of JSDoc based typings (inlining intrinsics at build time https://unpkg.com/browse/[email protected]/lib/ast-to-react.d.ts). export declare type NormalComponents = {
[TagName in keyof JSX.IntrinsicElements]: TagName | ((props: JSX.IntrinsicElements[TagName] & ReactMarkdownProps) => ReactNode);
}; not inline the |
Great, that would confirm the issue I'm seeing. I will try out your PR and see if that fixes it! Thank you for looking into this so fast! |
Co-authored-by: Remco Haszing <[email protected]> Reviewed-by: Remco Haszing <[email protected]> Reviewed-by: Titus Wormer <[email protected]> Related to GH-622. Closes GH-638.
Give version 7.0.1+ a try https://github.com/remarkjs/react-markdown/blob/main/changelog.md#701---2021-08-26 |
Sure, will do! I already tried with the PR and was successful in all I needed to do, so I'm sure that the new version will work as well! Thanks again, much appreciated! |
Subject of the issue
I think it is not possible to add components / renderers for custom tags like
myCustomTag
with typescript.
Problem
Lets say I'm using a plugin that creates custom tags e.g.
myCustomTag
and I want to render a custom component for it:Then I get a type error that
myCustomTag
is not allowed. This works fine if I setcomponents
to any.Expected behavior
I should be able to add component renderers for custom tags without typescript complaining.
It would be super cool if I could define custom tags with their respected properties…
The text was updated successfully, but these errors were encountered: