New dom-to-image plugin for saving DOM nodes as an image (#8810)

* Add tm-save-dom-to-image message

* Temporarily include the geospatial plugin in the Netlify previews

* Scale should default to 1x

* Fix saving SVG images

* Add example of saving in SVG format

* Add library version number

* Document peculiarities of JPEG quality parameter

* Allow format="jpg" as well as the more technically correct "jpeg"

* Document what happens if the selector returns multiple DOM nodes

* Refactor image-to-dom to be a separate plugin

* Add support for oncompletion handler

* Remove ELS marker

Thanks @ericshulman
This commit is contained in:
Jeremy Ruston
2026-02-06 10:42:40 +00:00
committed by GitHub
parent c96d398712
commit a3a4e91751
9 changed files with 279 additions and 2 deletions

View File

@@ -25,6 +25,61 @@ exports.startup = function() {
require("$:/plugins/tiddlywiki/geospatial/leaflet.markercluster.js");
}
// Install geolocation message handler
$tw.rootWidget.addEventListener("tm-save-dom-to-image",function(event) {
var params = event.paramObject || {},
domToImage = require("$:/plugins/tiddlywiki/geospatial/dom-to-image-more.js"),
domNode = document.querySelector(params.selector || "body.tc-body");
if(domNode) {
var method = "toPng";
switch(params.format) {
case "jpeg":
// Intentional fallthrough
case "jpg":
method = "toJpeg";
break;
case "svg":
method = "toSvg";
break;
}
domToImage[method](domNode,{
height: $tw.utils.parseInt(params.height) || domNode.offsetHeight,
width: $tw.utils.parseInt(params.width) || domNode.offsetWidth,
quality: $tw.utils.parseNumber(params.quality),
scale: $tw.utils.parseNumber(params.scale) || 1
})
.then(function(dataUrl) {
// Save the image
if(params["save-file"]) {
var link = document.createElement("a");
link.download = params["save-file"];
link.href = dataUrl;
link.click();
}
// Save the tiddler
if(params["save-title"]) {
if(dataUrl.indexOf("data:image/svg+xml;") === 0) {
var commaIndex = dataUrl.indexOf(",");
$tw.wiki.addTiddler(new $tw.Tiddler({
title: params["save-title"],
type: "image/svg+xml",
"text": decodeURIComponent(dataUrl.substring(commaIndex + 1))
}));
} else {
var parts = dataUrl.split(";base64,");
$tw.wiki.addTiddler(new $tw.Tiddler({
title: params["save-title"],
type: parts[0].split(":")[1],
"text": parts[1]
}));
}
}
})
.catch(function(error) {
console.error('oops, something went wrong!', error);
});
}
});
// Install geolocation message handler
$tw.rootWidget.addEventListener("tm-request-geolocation",function(event) {
var widget = event.widget,
wiki = widget.wiki || $tw.wiki,