graphql-markdown icon indicating copy to clipboard operation
graphql-markdown copied to clipboard

no control of markdown rendering

Open DanielFGray opened this issue 7 years ago • 2 comments

It would be ideal to support custom markdown renderers, to define custom marked options or even substitute marked entirely with eg react-markdown.

DanielFGray avatar Sep 26 '18 19:09 DanielFGray

@DanielFGray Thanks for creating this suggestion. Do you have any ideas/thoughts of how to achieve this?

We can expose the marked options to the end user for greater control (which might be a partial/short term solution), though I am guessing you would prefer to be using react-markdown or something else due to the way marked processes the markdown into html?

Would exposing the markdown content alongside the processed html via gql partially resolve this issue for you?
e.g -> query for content and request the .md, you can pass the unprocessed .md content to your react-markdown. Or are you wishing to completely switch out the .md processor?

contentItemById(id: "graphqlIntro") {
    id
    groupId
    markdown
    html
  }

cfnelson avatar Oct 03 '18 03:10 cfnelson

Personally, I would prefer to supply a function in the options that performs the markdown conversion, maybe something along the lines of:

runGraphqlMarkdown({
  contentRoot,
  render: md => {
    return myMarkdown(md)
  },
})

I'm sure that providing the original "raw" markdown in queries would also be helpful, but I would imagine less efficient if user wants to use that to create a custom markdown renderer..

Another idea that may be worth exploring is providing the markdown AST from something like remark-parse, although I think the use-case for this would also be solved with the custom renderer idea above.

If the render function is missing you could default to marked, my personal opinion would be to make that a new deprecation warning, and later create a breaking major version change and make the render function required. I think the migration from the current version should pretty much be as simple as:

const marked = require('marked')
marked.setOptions({ ...currentDefaults })
// ...
await runGraphqlMarkdown({
  contentRoot,
  render: md => marked(md),
})

It does make enabling syntax highlighting more tedious, depending on the libraries' API, but I think the trade-off for more flexible markdown parsing is worth it.

Edit: As another example for further motivation, currently there's no way to hook into marked's renderer. A user might expect to be able to add links to headings like GitHub does for readme files, which marked lets you do like:

const Marked = require('marked')
const renderer = new Marked.Renderer()
renderer.heading = function headings(text, level) {
  const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-')
  return `<h${level}><a name="${escapedText}" class="anchor" href="#${escapedText}"><span class="header-link">${'#'.repeat(level)}</span></a> ${text}</h${level}>`
}
Marked.setOptions({ renderer })

But the current API doesn't expose this, and changes to support it would only create further coupling to marked and create more work for you to support a greater amount of it's features..

DanielFGray avatar Oct 03 '18 20:10 DanielFGray