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

How to override inline/fenced code #6

Closed
usulpro opened this issue Aug 20, 2017 · 6 comments
Closed

How to override inline/fenced code #6

usulpro opened this issue Aug 20, 2017 · 6 comments
Labels
🙋 no/question This does not need any changes

Comments

@usulpro
Copy link

usulpro commented Aug 20, 2017

Thank you for this project and great ecosystem! I just started to learn how to use remark and retype and can't figure out how can I differentiate inline code vs block code.
My aim is to override these components with my own so I try to do it this way:

const components = {
  pre: ({props, children}) => <div style={{backgroundColor: 'hsl(0, 0%, 40%)', padding: 10}}>
    <pre>
      <code>
        {children}
      </code>
    </pre>
  </div>,
  code: ({props, children}) => <code className="code" style={{backgroundColor: 'hsl(0, 0%, 40%)'}}>
    {children}
  </code>,
}

// then

.use(rehype2react, {
    createElement: React.createElement,
    components,
  })

and of course, code affects both to inline and block code sections while I need to set separate components for them.
So could you point me the right way to do it?

@wooorm
Copy link
Member

wooorm commented Aug 20, 2017

Hmm, I dunno. “Block” and “Inline” are CSS concepts. In markdown, you have them too, but they refer more to <code> in <pre> and <code> in other stuff...

One thing I may have: check in the pre handler if there’s one node, and if it’s a code?

Otherwise: What’s your expected output? What are you passing in?

@usulpro
Copy link
Author

usulpro commented Aug 20, 2017

By inline I mean that goes in a single backquote like this: just string
And by block, I mean the triple backquoted code e.g:

.use(rehype2react, {
    createElement: React.createElement,
    components,
  })

At this moment I found a workaround like this:

components = {
code: ({props, children}) => <code {...props} 
    style={
      children.length > 1 ? {} :
      {
        border: '1px solid hsl(0, 0%, 80%)',
        borderRadius: 4,
        backgroundColor: 'hsl(0, 0%, 90%)',
        padding: '2px 4px',
        margin: '2px 6px',
      }}
    >
    {children}
  </code>,
}

this works at least when I use hilight.js because it inserts a lot of <span/> inside. In general I want to use separate <ReacComponent /> to handle "block" code and add some styles for "inline" code. If I could reach parent of component it would help? Some kind of this:

components = {
  code: ({props, children, parent}) => {
    if (parent.tag === 'pre') return <CodeMirrowComponent />
    return <CodeSpanComponent />
  },
}

Maybe it's not a right place to do it? Possible I need to handle this cases in remark level? I tried to dig into remark-vdom in order to pass some props/class names/something but without success yet

@rhysd
Copy link
Collaborator

rhysd commented Aug 21, 2017

I may miss the point...

I dug into parser code.

Inline code: https://github.com/wooorm/remark/blob/master/packages/remark-parse/lib/tokenize/code-inline.js
Fenced (Block) code: https://github.com/wooorm/remark/blob/master/packages/remark-parse/lib/tokenize/code-fenced.js

So, the type of token is different (inlineCode and code). To know which the <code> was from inline code or fenced code, I think they should be processed before converting MDAST into HAST. I guess you can write MDAST transform plugin and insert your own mark like class property at the node in order to distinguish inline/fenced code.

@wooorm
Copy link
Member

wooorm commented Aug 21, 2017

@rhysd That could work too!

@usulpro
Copy link
Author

usulpro commented Aug 21, 2017

@rhysd Thank you for pointing me that, I'll start to dig in this direction.

May I ask you one more question?

My chain looks this way:

unified()
    .use(remarkParser)
    .use(github, {
      repository: options.repository,
    })
    .use(remarkRehype)
    .use(highlight)
    .use(rehypeReact, {
      createElement: options.createElement,
      components: options.components,
    })

and for example, I try to override <a href=... />:

{
  a: ({ props, children }) =>
    <a
      {...props}
      style={{
        cursor: 'pointer',
        color: '#0366d6',
      }}
    >
      [props: {props} ]
      {children}
    </a>,
}

I'm expecting that props will contain a href field with value of my link. But props are always empty!
My guess is that it's because of sanitization?
But I can't find a place where I could disable this option ...or I do something wrong?

@usulpro usulpro changed the title How to override inline/block code How to override inline/fenced code Aug 21, 2017
@usulpro
Copy link
Author

usulpro commented Aug 21, 2017

Sorry, my fault!

components overriding function should look this way:

const components = {
  a: (props) => <a {...props} style={linkStyle}>{props.children}</a>,
  code: (props) => props.className ? <CodeFenced {...props} /> : <CodeInline {...props}/>,
}

in this case props for a contains href and props for code contains className='language-js' (only if you specify one in markdown)

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

No branches or pull requests

3 participants