saberland/saber

Expose the markdown parser

egoist opened this issue · 3 comments

Feature request

What problem does this feature solve?

Allow plugins to use this API to turn Markdown into HTML.

What does the proposed API look like?

const { html } = api.markdown.render(markdownCode, {
  defaultPlugins?: boolean,
  plugins?: MarkdownItPlugins[],
  options?: MarkdownItOptions,
  env?: object // Passed to `md.render`
})

Hey, I'm new to saber but I'd like to contribute if possible. As I understand it implementing this feature would mean taking some of the functionality from the markdown transformer and making it available on the saber instance so that plugins are able to make use of it?

@brattonross yes, like the api.pages API you can initialize it here:

this.pages = new Pages(this)

So currently the function signature that I have for render looks like this:

render(markdownCode, {
  defaultPlugins = true,
  plugins = [],
  options = {},
  env = {}
} = {}) {
  // ...
}

I'm assuming here that the second argument is optional, and that by default the default plugins should be used.

I then merge the options which are passed in with the existing options:

const chain = new ConfigChain()

chain.options.merge(
  Object.assign(
    {
      html: true,
      linkify: true,
      highlight: markdown.highlighter
    },
    markdown.options,
    options
  )
)

I have a couple of questions about the plugins; firstly, should the call to the chainMarkdown hook always happen, or only if we load default plugins? The current implementation that I have will only call it if the defaultPlugins flag is set. We could move the hook call outside of the if block, but then the plugins from config are loaded before this hook call, whereas previously the hook was called before these plugins were loaded. Also, are the plugins from config regarded as part of the default plugins? Or would the markdown transformer pass these in when calling the render method?

if (defaultPlugins) {
  // Load built-in plugins
  chain.loadPlugins(builtInPlugins, configDir)

  this.api.hooks.chainMarkdown.call(chain)

  // Load plugins from config file
  if (markdown.plugins) {
    chain.loadPlugins(markdown.plugins, configDir)
  }
}
// We could move the hook call here?

// Load user-defined plugins
chain.loadPlugins(plugins, )

Secondly, as you can see above I haven't passed a second argument to loadPlugins. I'm not sure currently what the cwd should be for these plugins. Will this be the same for all plugins or will the caller need to specify it for each plugin?