quire icon indicating copy to clipboard operation
quire copied to clipboard

`markdownify` returns stale unamended markdown library instance

Open cbutcosk opened this issue 1 year ago • 4 comments

Before proceeding, check to make sure there isn’t an existing issue for this bug.

  • [X] I have searched the existing issues and determined this is a new bug.

Steps to reproduce

  • Amend the markdown library using 11ty's amendLibrary API
  • Use markdownify to render markdown that uses the amended feature

Actual behavior

The rendered HTML does not include markdown renderer amendments.

Expected behavior

The rendered HTML should included markdown renderer amendments.

Version numbers

1.0.0-rc3

What browsers are you seeing the problem on?

No response

Relevant Terminal/Shell output

No response

Supporting Information

We worked around this by iterating the libraryAmendments array before the markdownlibrary instance is returned in markdownify, but 11ty has also lessened the need for a markdown rendering filter now that they released the renderTemplate API.

cbutcosk avatar Mar 16 '23 16:03 cbutcosk

Thanks @cbutcosk. Can you elaborate a bit on your use of amendLibrary? What was it you needed the markdown to do beyond Quire's normal functionality?

geealbers avatar Mar 20 '23 22:03 geealbers

On Exhibiting O'Keeffe we modify the markdown library to allow content editors to pass data attributes on link markup to front-end components. Editors insert a data-entity-reference="true"to indicate that the link should be picked up as a data reference to an API-backed entity and processed for the index of entities, etc.

These are then harvested by walking across all content and plucking the attributed elements out of the rendered stream, using renderTemplate in the harvesting loop so that the rendering can correctly handle whatever templating language it receives from underlying shortcodes.

We had been using markdownify in dev for this harvest-render but we discovered that it was returning a stale instance rather than the renderer 11ty was actually using as we expected. renderTemplate ultimately provided a better cut of what we needed (since it renders both markdown and liquid shortcodes with whatever is set as the render library, with amendments, and with appropriate parameter overrides where necessary) but since markdownify is used extensively in quire's component tooling we ended up needing to patch it to properly handle editor markup in other locations.

amendLibrary solves a need in quire projects because customizing render behaviors is a good way to encapsulate editor and content creator intent without increasing the size of the syntax they have to manage in markdown documents. From a long-term maintenance perspective as an integrator, the only thing better than creating a shortcode is not having to do so because HTML already covers the use case (which is very often the case!).

cbutcosk avatar Mar 21 '23 15:03 cbutcosk

@cbutcosk Wondering if you can provide some code for the customization you were using. I ran an extremely simple test and the markdownify filter does apply these modifications included in amendLibrary:

// .eleventy.js 
eleventyConfig.addPlugin(markdownPlugin)
eleventyConfig.amendLibrary('md', (markdownLibrary) => {
  markdownLibrary.renderer.rules.strong_open = () => `<gradoo>`
  markdownLibrary.renderer.rules.strong_close = () => `</gradoo>`
})

I'm currently working through an issue with rendering markdown footnotes inside shortcodes that's giving me a headache, and thinking through the whole template parsing flow. Replacing rid of the markdownify filter and using renderTemplate is definitely an interesting idea.

hbalenda avatar May 02 '23 19:05 hbalenda

@hbalenda The markdownify instance staling issue appeared in our case when:

  • We amended the renderer in a plugin
  • We used our blessed attribute on an intermediate component (Figure captions in our case) that use markdownify to render

Not sure if we needed both or if the latter always would have caused it.

Anyway 11ty's internal handling of amendments is pretty naive--amendments are closures, so they just iterate and execute the stack of closures on the render lib before returning it. So we did the same thing in markdownify's filter code:

  eleventyConfig.addFilter('markdownify', (content) => {
    if (!content) return ''

    for (let amendment of eleventyConfig.libraryAmendments['md'] || []) {
      amendment(markdownLibrary)        
    }      

    return !content.match(/\n/)
      ? markdownLibrary.renderInline(content)
      : markdownLibrary.render(content)
  })

Hope that helps in whatever way with your citation issue? It definitely sounds like renderTemplate might be more up your street if you're handling mixed markdown and liquid.

ETA: Adding the code to call renderTemplate since there's some ceremony to getting it on the eleventyConfig object. Remembering now that it also requires an async function, so you'd need to resolve any function coloring for callers in markdownify.

      // Use `renderTemplate` (see https://www.11ty.dev/docs/plugins/render/#rendertemplate) to render shortcodes (in our case for figures), then HTML
      let html = await eleventyConfig.javascriptFunctions.renderTemplate(post.template.frontMatter?.content,'liquid,md' ) 

cbutcosk avatar May 03 '23 12:05 cbutcosk