Skip to content

Instantly share code, notes, and snippets.

@derhuerst
Last active May 11, 2021 21:06
Show Gist options
  • Save derhuerst/3d73ddcb47365b50a801efc5fd5783a4 to your computer and use it in GitHub Desktop.
Save derhuerst/3d73ddcb47365b50a801efc5fd5783a4 to your computer and use it in GitHub Desktop.
remarkable picture plugin
'use strict'
const fs = require('fs')
const path = require('path')
const Remarkable = require('remarkable')
const picturePlugin = require('./picture-plugin')
const md = fs.readFileSync(path.join(__dirname, 'demo.md'), {encoding: 'utf8'})
const remarkable = new Remarkable({
html: true,
breaks: true,
typographer: true
})
remarkable.use(picturePlugin)
const html = remarkable.render(md)
console.log(html)

foo

foo bar baz

some alt text{some-class | (max-width: 40rem) 100vw, 40rem}

foo bar baz

'use strict'
const path = require('path')
const h = require('h2ml')
const {escapeHtml} = require('remarkable/lib/common/utils')
const modifierContent = /^\{\s*([^\}]+)\s*\}$/
const argsSep = /\s*\|\s*/
const parseModifier = (str) => {
let args = modifierContent.exec(str)
args = args && args[1] && args[1].split(argsSep)
return args && args.length > 0 ? args : null
}
const renderPicture = (_) => {
const srcset = []
const ext = path.extname(_.src)
const base = path.dirname(_.src) + '/' + path.basename(_.src, ext)
for (let width of [300, 600, 1200, 2400]) {
srcset.push(`${base}.${width}w${ext} ${width}w`)
}
const els = [
h('a', {
href: escapeHtml(_.src)
}, [
h('img', {
src: escapeHtml(_.src),
alt: escapeHtml(_.alt),
srcset: escapeHtml(srcset.join(', ')),
sizes: _.sizes ? escapeHtml(_.sizes) : ''
})
])
]
if (_.title) {
els.push(h('figcaption', {}, [
escapeHtml(_.title)
]))
}
return h('figure', {class: 'picture ' + _.classNames}, els)
}
const picturePlugin = (md) => {
const prevImgRule = md.renderer.rules.image
const enhancedImgRule = (tokens, i, opt, env) => {
const next = tokens[i + 1]
if (next && next.type === 'text') {
const args = parseModifier(next.content)
if (args) {
next.content = ''
// todo: break out of `<p>` wrapper
const ctx = {
src: tokens[i].src,
alt: tokens[i].alt,
title: tokens[i].title,
classNames: args[0],
sizes: args[1]
}
return renderPicture(ctx)
}
}
return prevImgRule.call(this, tokens, i, opt, env)
}
md.renderer.rules.image = enhancedImgRule
}
module.exports = picturePlugin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment