asciidoctor / asciidoctor-kroki

Asciidoctor.js extension to convert diagrams to images using Kroki!
https://kroki.io/
MIT License
146 stars 47 forks source link

Optionally use Data URLs to store generated image #397

Closed enrikb closed 3 weeks ago

enrikb commented 1 year ago

When playing with asciidoctor-kroki and various combinations of kroki-http-method and kroki-fetch-diagram, I had the idea to use Data URLs for storing the returned image data instead of files or just directly GETable URLs.

It has the advantage of exporting self-contained HTML versions of the documents. However, it does no longer allow caching already rendered diagrams well. (This is not so important for me as I'm using a local kroki server, anyway.)

The following patch contains a very quick'n'dirty proof-of-concept:

diff -ruN src/asciidoctor-kroki.js ../asciidoctor-vscode/node_modules/asciidoctor-kroki/src/asciidoctor-kroki.js
--- src/asciidoctor-kroki.js    2023-01-02 16:13:24.496477117 +0100
+++ ../asciidoctor-vscode/node_modules/asciidoctor-kroki/src/asciidoctor-kroki.js   2023-01-02 14:47:59.258352549 +0100
@@ -46,8 +46,11 @@

 const createImageSrc = (doc, krokiDiagram, target, vfs, krokiClient) => {
   const shouldFetch = doc.isAttribute('kroki-fetch-diagram')
+  const useDataURL = doc.isAttribute('kroki-fetch-into-data-url')
   let imageUrl
-  if (shouldFetch && doc.getSafe() < SAFE_MODE_SECURE) {
+  if (useDataURL) {
+    imageUrl = require('./fetch.js').save(krokiDiagram, doc, target, vfs, krokiClient, true)
+  } else if (shouldFetch && doc.getSafe() < SAFE_MODE_SECURE) {
     imageUrl = require('./fetch.js').save(krokiDiagram, doc, target, vfs, krokiClient)
   } else {
     imageUrl = krokiDiagram.getDiagramUri(krokiClient.getServerUrl())
diff -ruN src/fetch.js ../asciidoctor-vscode/node_modules/asciidoctor-kroki/src/fetch.js
--- src/fetch.js    2023-01-02 16:13:24.496477117 +0100
+++ ../asciidoctor-vscode/node_modules/asciidoctor-kroki/src/fetch.js   2023-01-02 14:41:37.114832748 +0100
@@ -21,7 +21,7 @@
   return baseDir
 }

-module.exports.save = function (krokiDiagram, doc, target, vfs, krokiClient) {
+module.exports.save = function (krokiDiagram, doc, target, vfs, krokiClient, use_data_url = false) {
   const exists = typeof vfs !== 'undefined' && typeof vfs.exists === 'function' ? vfs.exists : require('./node-fs.js').exists
   const read = typeof vfs !== 'undefined' && typeof vfs.read === 'function' ? vfs.read : require('./node-fs.js').read
   const add = typeof vfs !== 'undefined' && typeof vfs.add === 'function' ? vfs.add : require('./node-fs.js').add
@@ -45,11 +45,15 @@
   }
   // file is either (already) on the file system or we should read it from Kroki
   const contents = exists(filePath) ? read(filePath, encoding) : krokiClient.getImage(krokiDiagram, encoding)
-  add({
-    relative: imagesOutputDirectory,
-    basename: diagramName,
-    mediaType,
-    contents: Buffer.from(contents, encoding)
-  })
-  return diagramName
+  if (use_data_url) {
+    return 'data:' + mediaType + ";base64," + Buffer.from(contents, encoding).toString('base64')
+  } else {
+    add({
+      relative: imagesOutputDirectory,
+      basename: diagramName,
+      mediaType,
+      contents: Buffer.from(contents, encoding)
+    })
+    return diagramName
+  }
 }
ggrossetie commented 1 year ago

There are a few limitations when using data URI:

But I'm willing to implement this feature. Feel free to submit a pull request.