Use Edge template engine to render Dimer markdown AST
Note: This package is ESM only
The @dimerapp/edge
allows you to render the @dimerapp/markdown AST using Edge templates.
By using Edge as the rendering layer for Markdown, you can capture any AST node and render them using components.
Install the package from the npm registry as follows:
npm i @dimerapp/edge
# yarn
yarn add @dimerapp/edge
This package has a peer dependency on @dimerapp/markdown
. So make sure to install it as well.
npm i @dimerapp/markdown
# yarn
yarn add @dimerapp/markdown
Import the dimer
function and register it as the edge plugin. The function registers the neccessary helpers and in-memory templates to render the markdown AST.
import { Edge } from 'edge.js'
import { fileURLToPath } from 'node:url'
import { dimer, RenderingPipeline } from '@dimerapp/edge'
const viewsPath = fileURLToPath(new URL('./views', import.meta.url))
const edge = new Edge()
edge.mount(viewsPath)
edge.use(dimer)
const pipeline = new RenderingPipeline()
await edge.render('guide.edge', {
file: md,
pipeline
})
Next, create the guide.edge
file and paste the following markup inside it.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
@!component('dimer_contents', { nodes: file.ast.children, pipeline })~
</body>
</html>
That's all you need to do.
The benefit of generating the AST and then using a template engine to render its nodes comes in the form of flexbility.
In the following example, we capture the node with the tagName of pre
and render it using the elements/pre.edge
file. The second element inside the array is the props for edge component. You can name them as you like.
import { hasClass } from '@dimerapp/edge/utils'
import { RenderingPipeline } from '@dimerapp/edge'
const pipeline = new RenderingPipeline()
pipeline.use((node) => {
if (node.tagName === 'pre') {
return pipeline.component('elements/pre', { node })
}
})
Inside the edge file we wrap the pre tag inside a custom div and create a Copy to clipboard button to copy the contents of the codeblock to the clipboard.
Also, we are using Alpine.js to implement the frontend. For this example, you can pull in Alpine from the CDN.
<script src="//unpkg.com/alpinejs" defer></script>
<div x-data="{
copy() {
navigator.clipboard.writeText($root.querySelector('code').textContent)
}
}">
<button @click="copy"> Copy to clipboard </button>
@!component('dimer_element', { node, pipeline })~
</div>