Skip to content

dimerapp/edge

Repository files navigation

Dimer Edge

Use Edge template engine to render Dimer markdown AST

gh-workflow-image typescript-image npm-image license-image

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.

Setup

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

Usage

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.

Self rendering AST nodes

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>